package com.whxd.framework.common.web;

import java.io.IOException;
import java.util.Iterator;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.ModelAndView;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.whxd.framework.common.dto.ReturnObject;
import com.whxd.framework.common.exception.BusinessException;

/**
 * Spring Mvc 全局异常处理
 * 
 * @author 张世鹏
 * 
 */
public class GlobalControllerExceptionHandler implements HandlerExceptionResolver {

	private final static Logger log = LoggerFactory.getLogger(GlobalControllerExceptionHandler.class);

	@Override
	public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler,
			Exception ex) {

		log.info("错误转意，错误信息："+ex.getMessage());
		log.debug("记录commit以后出错的消息");
		if(response.isCommitted()){
           log.error(ex.getMessage(),ex);
        }


		ConstraintViolationException cve = getValidationExceptionFromCause(ex);
		if (cve != null) {
			ReturnObject ro = new ReturnObject();
			ro.setSuccess(false);
			String outMsg = "";
			Set<ConstraintViolation<?>> constraintViolations = cve.getConstraintViolations();
			Iterator<ConstraintViolation<?>> iterator = constraintViolations.iterator();
			while (iterator.hasNext()) {
				ConstraintViolation<?> cv = iterator.next();
				outMsg += "[" + cv.getPropertyPath() + "]" + cv.getMessage() + "\r\n";
			}
			response.setStatus(444);
			log.info(outMsg);
			ro.setMsg(outMsg);
			try {
				return new ModelAndView("msg", "msg", new ObjectMapper().writeValueAsString(ro));
			} catch (Exception e) {
				response.setStatus(500);
				log.error(e.getMessage(), e);
				return new ModelAndView("msg", "msg", e.getMessage());
			}

		} else if (ex instanceof BusinessException) {
			log.info(ex.getMessage());
			ReturnObject ro = new ReturnObject();
			ro.setMsg(ex.getMessage());
			ObjectMapper mapper = new ObjectMapper();
			try {
				return new ModelAndView("msg", "msg", mapper.writeValueAsString(ro));
			} catch (IOException e) {
				response.setStatus(500);
				log.error(e.getMessage(), e);
				return new ModelAndView("msg", "msg", e.getMessage());
			}
		} else if (ex instanceof AccessDeniedException) {
			log.debug(ex.getMessage());
			return null;
//		} else if (ex instanceof ClientAbortException) {
//			log.warn(ex.getMessage());
//			return null;
		} else {
			response.setStatus(500);
			log.error("其他错误类型："+ex.getMessage(), ex);
			return new ModelAndView("msg", "msg", ex.getMessage());
		}

	}

	private ConstraintViolationException getValidationExceptionFromCause(Throwable ex) {
		if (ex instanceof ConstraintViolationException) {
			return (ConstraintViolationException) ex;
		} else if (ex.getCause() != null) {
			return getValidationExceptionFromCause(ex.getCause());
		} else {
			return null;
		}
	}
}